﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using MathematicallySafe.HeadCounter.Data.Common;
using MathematicallySafe.HeadCounter.Commands;
using MathematicallySafe.HeadCounter.Data;
using MathematicallySafe.HeadCounter.Data.Models;
using MathematicallySafe.HeadCounter.Services;
using StructureMap;

namespace MathematicallySafe.HeadCounter.ViewModels
{
    public class RaidsViewModel: ViewModelBase
    {
        private static readonly IHeadCounterService HeadCounterService = ObjectFactory.GetInstance<IHeadCounterService>();

        private ObservableCollection<RaidViewModel> _raids;

        private DelegateCommand _deleteRaidCommand;
        private DelegateCommand _postRaidCommand;
        private DelegateCommand _deleteRaiderCommand;

        public RaidViewModel SelectedRaid { get; set; }

        public ListCollectionView Raids { get; private set; }

        public RaidsViewModel()
        {
            LoadRaids();
            Initialise();
        }

        private void LoadRaids()
        {
            _raids = new ObservableCollection<RaidViewModel>();
            HeadCounterService.RaidHistory.Raids.ForEach(AddRaid);

            Raids = new ListCollectionView(_raids);
            Raids.SortDescriptions.Add(new SortDescription("Date", ListSortDirection.Descending));

        }

        public ICommand DeleteRaidCommand
        {
            get
            {
                if (_deleteRaidCommand == null)
                {
                    _deleteRaidCommand = new DelegateCommand(DeleteSelectedRaid, CanDeleteSelectedRaid);
                }

                return _deleteRaidCommand;
            }
        }

        private void DeleteSelectedRaid()
        {
            if (MessageBox.Show(
                    "Are you sure you want to delete the " + SelectedRaid.Zone + " raid of " + SelectedRaid.Date.ToShortDateString() + "?",
                    "Confirm Delete", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                HeadCounterService.RaidHistory.RemoveRaid(SelectedRaid.Model);
            }
        }

        private bool CanDeleteSelectedRaid()
        {
            return SelectedRaid != null;
        }

        public ICommand PostRaidCommand
        {
            get
            {
                if (_postRaidCommand == null)
                {
                    _postRaidCommand = new DelegateCommand(PostSelectedRaid, CanPostSelectedRaid);
                }

                return _postRaidCommand;
            }
        }

        private void PostSelectedRaid()
        {
            ObjectFactory.GetInstance<IForumPostingService>().PostRaid(SelectedRaid.Model);
        }

        private bool CanPostSelectedRaid()
        {
            return SelectedRaid != null;
        }

        public ICommand DeleteRaiderCommand
        {
            get
            {
                if (_deleteRaiderCommand == null)
                {
                    _deleteRaiderCommand = new DelegateCommand(DeleteSelectedRaider, CanDeleteSelectedRaider);
                }

                return _deleteRaiderCommand;
            }
        }

        private void DeleteSelectedRaider()
        {
            var raiderName = SelectedRaid.SelectedRaider;
            var lootCount = SelectedRaid.Model.Loot.Count(l => l.Winner == raiderName);

            var lootMsg = lootCount > 0 ? " (And the " + lootCount + " items they won)" : null;

            if (MessageBox.Show(
                    "Are you sure you want to remove " + raiderName + lootMsg + " from the raid of " + SelectedRaid.Date.ToShortDateString() + "?",
                    "Confirm Delete", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            {
                SelectedRaid.Model.RemoveRaider(raiderName);
            }
        }

        private bool CanDeleteSelectedRaider()
        {
            return SelectedRaid != null  && !string.IsNullOrEmpty(SelectedRaid.SelectedRaider);
        }

        private void AddRaid(Raid raid)
        {
            var raidViewModel = new RaidViewModel(raid);
            raidViewModel.Initialise();

            _raids.Add(raidViewModel);
        }

        protected override void SubscribeEvents()
        {
            HeadCounterService.RaidHistory.RaidAdded += RaidAdded;
            HeadCounterService.RaidHistory.RaidRemoved += RaidRemoved;
        }

        protected override void UnsubscribeEvents()
        {
            HeadCounterService.RaidHistory.RaidAdded += RaidAdded;
            HeadCounterService.RaidHistory.RaidRemoved += RaidRemoved;
        }

        void RaidAdded(object sender, RaidsHistoryChangedEventArgs e)
        {
            AddRaid(e.Raid);
        }

        void RaidRemoved(object sender, RaidsHistoryChangedEventArgs e)
        {
            var raidViewModel = _raids.FirstOrDefault(r => r.Date == e.Raid.Date);

            if (raidViewModel != null)
            {
                _raids.Remove(raidViewModel);
                raidViewModel.Dispose();
            }
        }
    }
}
